如何跨域携带cookies

您所在的位置:网站首页 chrome 跨域cookie 如何跨域携带cookies

如何跨域携带cookies

#如何跨域携带cookies| 来源: 网络整理| 查看: 265

如何跨域携带cookies

通常情况下,浏览器是不允许http请求跨域携带cookies的,但凡事有例外,总有一些特殊场景,我们需要跨域携带cookies。

文章中demo,服务端代码使用nodejs 服务端框架koa2编写,客户端使用原生js编写。

场景

我们使用不同的端口号来制造跨域场景,测试http://localhost:3001上的js脚本 是否可以正常将cookies带给http://localhost:3000 的服务器。

http://localhost:3000服务端代码 服务端包含两个服务:

/api/info:访问这个服务,会为浏览器种下cookie

/api/hello: 我们期望通过这个服务,取回我们种在浏览器的cookie

服务端使用cors插件,设置origin:*允许了跨域访问 const path = require('path'); const Koa = require('koa'); const Router = require('koa-router'); const static = require('koa-static'); const cors = require('koa2-cors'); const router = new Router(); router.get('/api/info', async (ctx) => { ctx.cookies.set( 'cid', '000000', { domain: 'localhost', // 写cookie所在的域名 path: '/', // 写cookie所在的路径 maxAge: 10 * 60 * 1000, // cookie有效时长 expires: new Date('2021-02-15'), // cookie失效时间 httpOnly: false, // 是否只用于http请求中获取 overwrite: false // 是否允许重写 } ) ctx.body = 'success' }).get('/api/hello', async (ctx) => { const cid = ctx.cookies.get('cid'); ctx.body = { cid: cid, } }) const app = new Koa(); const corsParams = { origin: '*', } app.use(cors(corsParams)); app.use(static(path.join(__dirname, './static'))); app.use(router.routes()).use(router.allowedMethods()); app.listen(process.env.PORT || '3000'); 复制代码 http://localhost:3001/index1.html脚本

index1.html上的脚本会进行如下两步操作:

自动请求一次http://localhost:3000服务器上的/api/info服务,来种下cookie 然后手动点击按钮,请求/api/hello接口,看是否可以将cookie带给http://localhost:3000服务器 DOCTYPE html> Document hello 发送 setCookies() function setCookies() { const xhr = new XMLHttpRequest(); xhr.open('get', '//localhost:3000/api/info') xhr.send(); } function hello() { const xhr = new XMLHttpRequest(); xhr.open('get', '//localhost:3000/api/hello') xhr.send(); } 复制代码

从结果中可以看出/api/info相应头中包含Set-cookie

但是之后的/api/hello请求头中并没有带有cookie

Credentials

这是因为跨域请求的情况下,浏览器默认禁止携带cookie,如果想携带cookie,需要在请求时设置withCredentials参数为true,然后我们像下面这样修改 hello方法,再次实验。

function setCookies() { const xhr = new XMLHttpRequest(); xhr.open('get', '//localhost:3000/api/info') // 这里也需要加,不然浏览器会忽略 /api/info 种的cookie xhr.withCredentials = true; xhr.send(); // 使用fetch方法 // fetch('//localhost:3000/api/info', {credentials: 'include'}).then((res) => { // console.log(res); // }) } function hello() { const xhr = new XMLHttpRequest(); xhr.open('get', '//localhost:3000/api/hello') xhr.withCredentials = true; xhr.send(); // 使用fetch方法 // fetch('//localhost:3000/api/hello', {credentials: 'include'}).then((res) => { // console.log(res); // }) } 复制代码

发现浏览器控制台直接报错了:

根据错误提示:当请求的credentials模式为include时,响应头Access-Control-Origin的值不可以是*,也就是说服务端的cors插件的origin参数,必须指定具体域名,而不能是*这种通配符。然后我们将服务端代码做如下调整,并再次实验。

... const app = new Koa(); const corsParams = { origin: 'http://localhost:3001', } app.use(cors(corsParams)); ... 复制代码

然后发现竟然又报错了

根据错误提示:当请求的credentials模式是include时,响应头Access-Control-Credentials的值应该是true,不应该是'',所以这次是服务端响应头的设置的问题。我们观察响应头,确实没有设置Access-Control-Credentials

于是修改服务端代码:

... const app = new Koa(); const corsParams = { origin: 'http://localhost:3001', credentials: true, } app.use(cors(corsParams)); ... 复制代码

再次发送,请求头中包含了Cookie,响应头中包含了Access-Control-Credentials,并不再报错。

总结

服务端需要设置

Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: [特定域名] // 不可以是* 复制代码

客户端

XMLHttpRequest发请求需要设置withCredentials=true,fetch 发请求需要设置 credentials = include

参考

developer.mozilla.org/en-US/docs/…



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3